package com.hillstone.component.cloud.ngcv.component.aop.aspect;


import com.hillstone.cloud.ngcv.common.errorcode.NgcvCommonError;
import com.hillstone.component.cloud.ngcv.component.aop.annotation.RedisLock;
import com.hillstone.component.cloud.ngcv.component.aop.util.AnnotationResolver;
import com.hillstone.cloud.platform.error.code.errorcode.CloudException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * @author wangjian2
 * @date 2022/3/14 9:44
 * @descripton
 */
@Aspect
@Component
public class RedisAspect {

    @Autowired
    private RedisLockRegistry redisLockRegistry;

    @Around(value = "@annotation(redisLock)")
    public Object around(ProceedingJoinPoint pjp, RedisLock redisLock) throws Throwable {
        String keyPrefix = redisLock.keyPrefix();
        String key = AnnotationResolver.newInstance().resolver(pjp, redisLock.key(), keyPrefix);

        Lock lock = redisLockRegistry.obtain(key);
        if (redisLock.tryLockTime() < 0) {
            lock.lock();
        } else if (!lock.tryLock(redisLock.tryLockTime(), TimeUnit.SECONDS)) {
             throw new CloudException(NgcvCommonError.SYSTEM_BUSY);
        }
        try {
            return pjp.proceed();
        } finally {
            lock.unlock();
        }
    }



}
